import * as vscode from "vscode";
import { GitChangeDetector } from "./gitChanges";
import { CacheManager } from "./cacheManager";
import OpenAI from "openai";

class CommitAIViewProvider implements vscode.WebviewViewProvider {
  public static readonly viewType = "commit-ai-view";

  constructor(private readonly _extensionUri: vscode.Uri) {}

  private async getGitChanges(workspaceRoot: string) {
    try {
      const detector = new GitChangeDetector(workspaceRoot);
      const changes = await detector.getChangedFiles();

      // 构建 JSON 对象
      const gitData = {
        workspace: workspaceRoot,
        timestamp: new Date().toISOString(),
        changes: changes,
      };

      return gitData;
    } catch (error: unknown) {
      throw error;
    }
  }

  public resolveWebviewView(
    webviewView: vscode.WebviewView,
    context: vscode.WebviewViewResolveContext,
    _token: vscode.CancellationToken
  ) {
    webviewView.webview.options = {
      enableScripts: true,
      localResourceRoots: [this._extensionUri],
    };

    try {
      this._updateWebview(webviewView.webview, context);
    } catch (error: unknown) {}

    // 处理来自 Webview 的消息
    webviewView.webview.onDidReceiveMessage(async (message) => {
      switch (message.command) {
        case "fetchData":
          try {
            // 获取当前工作区路径
            const workspaceRoot =
              vscode.workspace.workspaceFolders?.[0].uri.fsPath;
            if (!workspaceRoot) {
              throw new Error("No workspace folder found");
            }

            // 获取 Git 变更信息
            const gitData = await this.getGitChanges(workspaceRoot);

            // 发送消息给 Webview，显示 API 调用提示
            webviewView.webview.postMessage({
              command: "gitDataFetched",
            });

            const customPrompt = message.customPrompt;
            const apiKey = message.apiKey;
            // 保存 API key 到缓存
            CacheManager.getInstance().setDifyApiKey(apiKey);
            CacheManager.getInstance().setCustomPrompt(customPrompt);

            if (!customPrompt.includes("[data]")) {
              vscode.window.showErrorMessage("自定义提示词必须包含[data]");
              return;
            }

            let query = customPrompt.replace("[data]", JSON.stringify(gitData));

            console.warn("git数据");
            console.warn(JSON.stringify(gitData));

            // 发送数据到 API
            const openai = new OpenAI({
              baseURL: "https://api.deepseek.com",
              apiKey: apiKey,
            });

            const systemPrompt = `我是一个AI commit 工具， 我需要根据你的需求，生成git commit信息，基础的操作方式和注意事项。

1. 先通过 git status 查看哪些文件进行了修改, 修改了哪些行。

2. 通过 git diff 来查看修改的具体内容

3. 针对修改的内容，以文件维度逐条描述，输出内容参考下面的输出规则。 输出示例可以作为输出格式借鉴。

4. 实际的 [data] 是整理好的git json数据，下面是一份demo数据。
{
  "workspace": "D:/project/path", // 工作区路径
  "timestamp": "2025-01-13T20:34:19+08:00", // 获取数据的时间戳
  "branch": "main", // 当前分支名称
  "changes": {
    "summary": {
      "total_files": 3, // 变更的总文件数
      "additions": 50, // 总新增行数
      "deletions": 20 // 总删除行数
    },
    "files": [
      {
        "path": "src/extension.ts", // 文件路径
        "status": "modified", // 文件状态：modified(修改), added(新增), deleted(删除), renamed(重命名)
        "stats": {
          "additions": 30, // 该文件新增行数
          "deletions": 10 // 该文件删除行数
        },
        "changes": [
          {
            "type": "addition", // 变更类型：addition(新增), deletion(删除), modification(修改)
            "line_number": 25, // 变更发生的行号
            "content": "+ const newCode = 'example';", // 变更的具体内容
            "old_content": null // 如果是修改，这里显示修改前的内容
          },
          {
            "type": "modification",
            "line_number": 30,
            "content": "- const updatedCode = 'new';",
            "old_content": "- const oldCode = 'old';"
          }
        ]
      },
      {
        "path": "package.json",
        "status": "modified",
        "stats": {
          "additions": 20,
          "deletions": 10
        },
        "changes": [
          {
            "type": "addition",
            "line_number": 15,
            "content": "+    \"axios\": \"^1.6.5\"",
            "old_content": null
          }
        ]
      }
    ],
    "untracked": [
      // 未跟踪的文件列表
      {
        "path": "temp.log",
        "type": "file" // file 或 directory
      }
    ]
  }
}

5. 你根据实际提供的 [data] 和输出要求，进行内容输出。
`;

            const completion = await openai.chat.completions.create({
              messages: [
                {
                  role: "system",
                  content: systemPrompt,
                },
                {
                  role: "user",
                  content: query,
                },
              ],
              model: "deepseek-chat",
              stream: true,
            });

            let fullResponse = "";

            try {
              for await (const chunk of completion) {
                const content = chunk.choices[0]?.delta?.content || "";
                if (content) {
                  fullResponse += content;
                  // 发送部分结果给 Webview
                  webviewView.webview.postMessage({
                    command: "streamResponse",
                    text: fullResponse,
                  });
                }
              }

              // 发送完整结果
              webviewView.webview.postMessage({
                command: "updateResult",
                text: JSON.stringify({
                  apiResponse: fullResponse,
                }),
              });
            } catch (error) {
              console.error("Streaming error:", error);
              webviewView.webview.postMessage({
                command: "error",
                error:
                  error instanceof Error
                    ? error.message
                    : "Streaming error occurred",
              });
            }
          } catch (error: unknown) {
            webviewView.webview.postMessage({
              command: "updateResult",
              text: JSON.stringify(
                {
                  error:
                    error instanceof Error
                      ? error.message
                      : "Failed to fetch data",
                },
                null,
                2
              ),
            });
          }
          break;
      }
    });

    webviewView.onDidChangeVisibility(() => {
      if (webviewView.visible) {
        this._updateWebview(webviewView.webview, context);
      }
    });
  }

  private _updateWebview(
    webview: vscode.Webview,
    context: vscode.WebviewViewResolveContext
  ) {
    const apiKey = CacheManager.getInstance().getDifyApiKey() || "";
    const customPrompt =
      CacheManager.getInstance().getCustomPrompt() ||
      `需求：根据数据源，生成一份git commit 文案
文案规则：
1. markdown格式，返回。
2. 输出每一个改动的文件，及改动的内容是什么。

数据：[data]

输出示例：

feat✨ xxxxx(这里是一个简单的修改概述)

# 修改的文件

- src/xxx/xxx/index.vue

# 修改的内容

- 更新了 [src/xxx/xxx/index.vue]
  1. 修改了xxx的显隐逻辑。
  2. 修改了yyy的判断。
  3. 新增了xxxx功能`;

    const html = `<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline' https://cdn.jsdelivr.net;">
        <title>Commit AI</title>
        <style>
            body {
                padding: 10px;
                color: var(--vscode-foreground);
                font-family: var(--vscode-font-family);
                background-color: var(--vscode-editor-background);
            }
            h1 {
                font-size: 1.2em;
                margin-bottom: 1em;
                color: var(--vscode-foreground);
            }
            .button {
                background-color: var(--vscode-button-background);
                color: var(--vscode-button-foreground);
                padding: 8px 16px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                margin: 10px 0;
                width: 100%;
            }
            .button:hover {
                background-color: var(--vscode-button-hoverBackground);
            }
            #result {
                margin-top: 10px;
                padding: 10px;
                background-color: var(--vscode-input-background);
                border: 1px solid var(--vscode-input-border);
                border-radius: 4px;
                min-height: 60px;
                word-break: break-word;
                white-space: pre-wrap;
                font-family: var(--vscode-editor-font-family);
                max-height: 400px;
                overflow-y: auto;
            }
            .button-group {
                display: flex;
                gap: 8px;
                margin-top: 5px;
            }
            .copy-button {
                background-color: var(--vscode-button-secondaryBackground);
                color: var(--vscode-button-secondaryForeground);
                padding: 4px 8px;
                border: none;
                border-radius: 2px;
                cursor: pointer;
                font-size: 0.9em;
            }
            .loading {
                display: none;
                margin: 10px 0;
                color: var(--vscode-descriptionForeground);
            }
            .loading-spinner {
                display: inline-block;
                width: 16px;
                height: 16px;
                border: 2px solid var(--vscode-descriptionForeground);
                border-radius: 50%;
                border-top-color: transparent;
                animation: spin 1s linear infinite;
                margin-right: 8px;
                vertical-align: middle;
            }
            @keyframes spin {
                to {
                    transform: rotate(360deg);
                }
            }
            .step-message {
                display: none;
                margin: 10px 0;
                padding: 8px;
                border-radius: 4px;
                background-color: var(--vscode-textBlockQuote-background);
                color: var(--vscode-foreground);
            }
            .logs-container {
                margin: 10px 0;
                padding: 8px;
                background-color: var(--vscode-textBlockQuote-background);
                border-radius: 4px;
                max-height: 100px;
                overflow-y: auto;
            }
            .log-item {
                margin: 4px 0;
                font-family: var(--vscode-editor-font-family);
                font-size: 12px;
                color: var(--vscode-foreground);
            }
            .log-time {
                color: var(--vscode-descriptionForeground);
                margin-right: 8px;
            }
            .log-success {
                color: var(--vscode-testing-iconPassed);
            }
            .log-info {
                color: var(--vscode-foreground);
            }
            .log-error {
                color: var(--vscode-errorForeground);
            }
            .input-field {
                margin: 10px 0;
            }
            .input-field label {
                display: block;
                margin-bottom: 5px;
                color: var(--vscode-foreground);
                font-weight: 500;
            }
            .input-field .steps {
                margin-bottom: 10px;
            }
            .input-field .steps label {
                font-weight: normal;
                margin-bottom: 2px;
            }
            .input-field input {
                width: 100%;
                padding: 8px;
                background-color: var(--vscode-input-background);
                color: var(--vscode-input-foreground);
                border: 1px solid var(--vscode-input-border);
                border-radius: 4px;
                font-family: var(--vscode-editor-font-family);
                margin-bottom: 10px;
            }
            .input-field textarea {
                width: 100%;
                padding: 8px;
                background-color: var(--vscode-input-background);
                color: var(--vscode-input-foreground);
                border: 1px solid var(--vscode-input-border);
                border-radius: 4px;
                font-family: var(--vscode-editor-font-family);
                resize: vertical;
                min-height: fit-content;
                max-height: 400px;
                height: auto;
                overflow-y: auto;
            }
            .error-message {
                color: var(--vscode-errorForeground);
                margin: 5px 0;
                display: none;
            }
            .help-button {
                position: absolute;
                top: 10px;
                right: 10px;
                background-color: transparent;
                border: none;
                color: var(--vscode-foreground);
                cursor: pointer;
                font-size: 16px;
                padding: 5px;
                display: flex;
                align-items: center;
                opacity: 0.7;
            }
            .help-button:hover {
                opacity: 1;
            }
            .modal {
                display: none;
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background-color: rgba(0, 0, 0, 0.5);
                z-index: 1000;
            }
            .modal-content {
                position: relative;
                background-color: var(--vscode-editor-background);
                margin: 15% auto;
                padding: 20px;
                border: 1px solid var(--vscode-input-border);
                border-radius: 4px;
                width: 80%;
                max-width: 500px;
            }
            .close-button {
                position: absolute;
                right: 10px;
                top: 10px;
                cursor: pointer;
                background: none;
                border: none;
                color: var(--vscode-foreground);
                font-size: 18px;
                opacity: 0.7;
            }
            .close-button:hover {
                opacity: 1;
            }
            .steps-modal {
                margin-top: 20px;
                line-height: 1.6;
            }
            .steps-modal ol {
                padding-left: 20px;
                margin: 10px 0;
            }
            .steps-modal li {
                margin: 8px 0;
            }
        </style>
    </head>
    <body>
        <h1>Dify GitCommit Generator</h1>
        <button class="help-button" onclick="showHelp()">
            帮助
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5ZM8 13C5.23858 13 3 10.7614 3 8C3 5.23858 5.23858 3 8 3C10.7614 3 13 5.23858 13 8C13 10.7614 10.7614 13 8 13Z" fill="currentColor"/>
                <path d="M8 6C7.44772 6 7 6.44772 7 7V10C7 10.5523 7.44772 11 8 11C8.55228 11 9 10.5523 9 10V7C9 6.44772 8.55228 6 8 6Z" fill="currentColor"/>
                <circle cx="8" cy="5" r="1" fill="currentColor"/>
            </svg>
        </button>
        <div id="helpModal" class="modal">
            <div class="modal-content">
                <button class="close-button" onclick="closeHelp()">×</button>
                <h2>使用说明</h2>
                <div class="steps-modal">
                    <ol>
                        <li><strong>修改的代码暂存</strong> - 首先确保你要提交的代码已经通过 git add 添加到暂存区</li>
                        <li><strong>编辑提示词(可选)</strong> - 可以根据需要修改提示词模板，[data] 会被替换为实际的 Git 变更数据</li>
                        <li><strong>添加DeepSeek API Key</strong> - 输入你的 DeepSeek API Key (格式必须是 sk- 开头)</li>
                        <li><strong>生成commit信息</strong> - 点击按钮生成规范的 commit 信息</li>
                    </ol>
                    <p>提示：生成的 commit 信息支持复制原文或 Markdown 格式</p>
                </div>
            </div>
        </div>
        <div class="input-field">
            <div style="width: 100%;">
                <label>DeepSeek API Key</label>
                <input type="text" id="apiKey" style="max-width: 400px" value="${apiKey}" placeholder="请输入你的API Key (格式: sk-...)" />
                <div id="apiKeyError" class="error-message">请输入有效的API Key (格式: sk-...)</div>
            </div>
            <div style="width: 100%;">
                <label>提示词：[data] 是git暂存的数据</label>
                <textarea style="max-height: 400px;min-height:200px" id="customPrompt" placeholder="在这里输入完整的提示词，使用 [data] 作为数据占位符">${customPrompt}</textarea>
            </div>
        </div>
        <div class="logs-container" id="logsContainer"></div>
        <div id="gitLoading" class="step-message">
            <span class="loading-spinner"></span>
            <span>正在获取Git变更信息...</span>
        </div>
        <div id="apiLoading" class="step-message">
            <span class="loading-spinner"></span>
            <span>正在生成Commit信息...</span>
        </div>
        <button class="button" onclick="fetchData()">生成commit信息</button>
        <label>生成的数据：</label>
        <div id="result"></div>
        <div class="button-group">
            <button id="copyMarkdownButton" class="copy-button" style="display: none;" onclick="copyToClipboard('markdown')">复制Markdown</button>
        </div>
        <script>
            const vscode = acquireVsCodeApi();
            let markdownContent = '';

            function addLog(message, type = 'info') {
                const logsContainer = document.getElementById('logsContainer');
                const now = new Date();
                const timeStr = now.toLocaleTimeString();
                const logItem = document.createElement('div');
                logItem.className = 'log-item';
                logItem.innerHTML = '<span class="log-time">' + timeStr + '</span><span class="log-' + type + '">' + message + '</span>';
                logsContainer.appendChild(logItem);
                logsContainer.scrollTop = logsContainer.scrollHeight;
            }

            function validateApiKey(apiKey) {
                return apiKey && apiKey.startsWith('sk-') && apiKey.length >= 32;
            }

            function fetchData() {
                const apiKey = document.getElementById('apiKey').value.trim();
                const apiKeyError = document.getElementById('apiKeyError');

                if (!validateApiKey(apiKey)) {
                    apiKeyError.style.display = 'block';
                    return;
                }

                apiKeyError.style.display = 'none';
                document.getElementById('result').textContent = '';
                document.getElementById('copyMarkdownButton').style.display = 'none';

                // 清空日志
                document.getElementById('logsContainer').innerHTML = '';

                // 显示Git加载提示
                document.getElementById('gitLoading').style.display = 'block';
                document.getElementById('apiLoading').style.display = 'none';

                addLog('开始获取本地Git信息...');

                const customPrompt = document.getElementById('customPrompt').value;
                vscode.postMessage({
                    command: 'fetchData',
                    customPrompt: customPrompt,
                    apiKey: apiKey
                });
            }

            function copyToClipboard(format) {
                const textToCopy = markdownContent;
                navigator.clipboard.writeText(textToCopy).then(() => {
                    const button = document.getElementById('copyMarkdownButton');
                    button.textContent = '已复制！';
                    setTimeout(() => {
                        button.textContent = '复制Markdown';
                    }, 2000);
                });
            }

            function showHelp() {
                document.getElementById('helpModal').style.display = 'block';
            }

            function closeHelp() {
                document.getElementById('helpModal').style.display = 'none';
            }

            // 点击模态框外部关闭
            window.onclick = function(event) {
                const modal = document.getElementById('helpModal');
                if (event.target === modal) {
                    modal.style.display = 'none';
                }
            }

            window.addEventListener('message', event => {
                const message = event.data;
                switch (message.command) {
                    case 'gitDataFetched':
                        // Git数据获取完成，显示API调用提示
                        addLog('Git信息获取成功', 'success');
                        addLog('开始请求Commit生成接口...');
                        document.getElementById('gitLoading').style.display = 'none';
                        document.getElementById('apiLoading').style.display = 'block';
                        // 清空之前的结果
                        document.getElementById('result').innerHTML = '';
                        document.getElementById('copyMarkdownButton').style.display = 'none';
                        break;
                    case 'streamResponse':
                        // 处理流式响应
                        document.getElementById('gitLoading').style.display = 'none';
                        document.getElementById('apiLoading').style.display = 'block';
                        const resultDiv = document.getElementById('result');

                        // 使用marked.parse处理新的文本
                        resultDiv.innerHTML = marked.parse(message.text);

                        // 自动滚动到底部
                        resultDiv.scrollTop = resultDiv.scrollHeight;
                        break;
                    case 'updateResult':
                        // API调用完成，显示最终结果
                        document.getElementById('gitLoading').style.display = 'none';
                        document.getElementById('apiLoading').style.display = 'none';

                        try {
                            const data = JSON.parse(message.text);
                            if (data.error) {
                                addLog('接口返回错误: ' + data.error, 'error');
                                return;
                            }
                            addLog('Commit信息生成完成', 'success');
                            markdownContent = data.apiResponse;

                            // 最后一次完整渲染
                            const resultDiv = document.getElementById('result');
                            resultDiv.innerHTML = marked.parse(data.apiResponse);

                            // 显示复制按钮
                            document.getElementById('copyMarkdownButton').style.display = 'block';
                        } catch (error) {
                            addLog('解析响应失败: ' + error.message, 'error');
                        }
                        break;
                    case 'error':
                        // 处理错误消息
                        document.getElementById('gitLoading').style.display = 'none';
                        document.getElementById('apiLoading').style.display = 'none';
                        addLog('错误: ' + message.error, 'error');
                        break;
                }
            });
        </script>
        <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    </body>
    </html>`;

    webview.html = html;
  }
}

export function activate(context: vscode.ExtensionContext) {
  try {
    // 初始化缓存管理器
    CacheManager.getInstance(context);

    const provider = new CommitAIViewProvider(context.extensionUri);

    context.subscriptions.push(
      vscode.window.registerWebviewViewProvider(
        CommitAIViewProvider.viewType,
        provider
      )
    );

    let disposable = vscode.commands.registerCommand(
      "commit-ai.helloWorld",
      () => {
        vscode.window.showInformationMessage("Hello Commit AI!");
      }
    );

    context.subscriptions.push(disposable);
  } catch (error: unknown) {}
}

export function deactivate() {}
